package org.wattdepot.cli;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClientException;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Provides the methods to output the chart command given specific data.
 * 
 * @author Scott Wong and Kelli Sawai
 * 
 */
public class ChartCommand extends CommandLineInterface implements WattDepotCliCommand {

  /**
   * Creates a file with the requested graph data.
   * 
   * @param args The data requested to make the graph.
   * @return No return value since the data is written to a file.
   */
  public String doCommand(String args) {
    try {
      if (args.matches("chart power [generated|consumed]+ \\S* \\S* \\S* "
          + "sampling-interval \\w* file \\S*")) {
        String[] chartInput = args.split("\\s");
        String type = chartInput[2];
        String source = chartInput[3];
        XMLGregorianCalendar startDay = toTimestamp(chartInput[4]);
        XMLGregorianCalendar endDay = toTimestamp(chartInput[5]);

        // Check if the timestamp is in the future.
        XMLGregorianCalendar now;
        now =
            DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(new GregorianCalendar());

        if (startDay.compare(now) >= 0) {
          return futureTimestampMessage;
        }

        int minutes = Integer.parseInt(chartInput[7]);
        String fileName = "C:\\" + chartInput[9];

        FileOutputStream outputFile = new FileOutputStream(fileName);
        BufferedOutputStream out = new BufferedOutputStream(outputFile);
        String output = chartPower(type, source, startDay, endDay, minutes);
        out.write(output.getBytes());
        out.flush();
        out.close();
        outputFile.close();
        if (!output.contains("Error: Resource not found")) {
          output = ("Wrote: " + fileName);
        }
        return output;
      }
      else {
        return "The command you have entered is invalid.";
      }

    }
    catch (WattDepotClientException e) {
      return "An error occured while executing the requested command.";
    }
    catch (Exception e) {
      return "An error occured while executing the requested command.";
    }
  }

  /**
   * Gets the data for the chart.
   * 
   * @param type Generated or consumed
   * @param source The source to chart
   * @param startDay The start of the chart.
   * @param endDay The end of the chart.
   * @param minutes The interval to chart.
   * @return The chart link.
   * @throws WattDepotClientException If error occurs.
   */
  public String chartPower(String type, String source, XMLGregorianCalendar startDay,
      XMLGregorianCalendar endDay, int minutes) throws WattDepotClientException {
    try {
      XMLGregorianCalendar day = startDay;
      Double power;
      Double minPower = (client.getPowerGenerated(source, day)) / 1000000;
      Double maxPower = 0.0;
      StringBuffer buffer = new StringBuffer(300);
      buffer.append("<html><body><img src=\""
          + "http://chart.apis.google.com/chart?chs=250x100&cht=lc&chd=t:");

      if (type.compareToIgnoreCase("generated") == 0) {
        while (Tstamp.lessThan(day, endDay)) {
          // Convert from W to MW
          power = (client.getPowerGenerated(source, day)) / 1000000;
          buffer.append(Double.toString(power)).append(cm);
          if (power < minPower) {
            minPower = power;
          }
          if (power > maxPower) {
            maxPower = power;
          }
          day = Tstamp.incrementMinutes(day, minutes);
        }
      }
      else {
        while (Tstamp.lessThan(day, endDay)) {
          // Convert from W to MW
          power = (client.getPowerConsumed(source, day)) / 1000000;
          buffer.append(Double.toString(power)).append(cm);
          if (power < minPower) {
            minPower = power;
          }
          if (power > maxPower) {
            maxPower = power;
          }
          day = Tstamp.incrementMinutes(day, minutes);
        }
      }
      buffer.deleteCharAt(buffer.length() - 1);
      buffer.append(String.format("&chds=%.1f,%.1f&chxt=y&chxr=0,%.1f,%.1f", minPower,
          maxPower, minPower, maxPower));
      buffer.append("\" /></body></html>");
      return buffer.toString();
    }
    catch (MiscClientException e) {
      return "Error: WattDepot client encountered an error";
    }
    catch (ResourceNotFoundException e1) {
      return resourceMessage;
    }
  }

}
